Micron Document
<!DOCTYPE html>
<html class="client-nojs vector-feature-language-in-header-enabled vector-feature-language-in-main-page-header-disabled vector-feature-page-tools-pinned-disabled vector-feature-toc-pinned-clientpref-0 vector-toc-not-available vector-feature-main-menu-pinned-disabled vector-feature-limited-width-clientpref-1 vector-feature-limited-width-content-enabled vector-feature-custom-font-size-clientpref-1 vector-feature-appearance-pinned-clientpref-0 skin-theme-clientpref-day vector-sticky-header-enabled" lang="de" dir="ltr"><head>
<meta charset="UTF-8">
<title>SQL-Injection</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="icon" type="image/png" href="./_res_/favicon.png">
<link rel="canonical" href="https://de.wikipedia.org/wiki/SQL-Injection"> <link href="./_mw_/ext.cite.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.pygments.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.wikimediamessages.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.icons.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.search.codex.styles.css" rel="stylesheet" type="text/css">
<link href="./_mw_/skins.vector.styles.css" rel="stylesheet" type="text/css">
<meta name="ResourceLoaderDynamicStyles" content="">
<link href="./_mw_/ext.gadget.citeRef.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.defaultPlainlinks.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonHide.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonLayout.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiCommonStyle.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiDarkmode.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.dewikiResponsive.css" rel="stylesheet" type="text/css">
<link href="./_mw_/ext.gadget.specialSearch.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" type="text/css" href="./_mw_/site.styles.css">
<link rel="stylesheet" type="text/css" href="./_mw_/noscript.css">
<link rel="stylesheet" type="text/css" href="./_res_/footer.css">
<link rel="stylesheet" type="text/css" href="./_res_/vector-2022.css">
</head>
<body class="skin--responsive skin-vector skin-vector-search-vue mediawiki ltr sitedir-ltr mw-hide-empty-elt ns-0 ns-subject page-SQL-Injection rootpage-SQL-Injection skin-vector-2022 action-view">
<div class="mw-page-container">
<div class="mw-page-container-inner">
<div class="mw-content-container">
<main id="content" class="mw-body">
<header class="mw-body-header vector-page-titlebar">
<h1 id="firstHeading" class="firstHeading mw-first-heading"><span class="mw-page-title-main">SQL-Injection</span></h1>
</header>
<a id="top"></a>
<div id="bodyContent" class="vector-body ve-init-mw-desktopArticleTarget-targetContainer" aria-labelledby="firstHeading" data-mw-ve-target-container="">
<div id="contentSub">
<div id="mw-content-subtitle"></div>
</div>
<div id="mw-content-text" class="mw-body-content mw-content-ltr" lang="de" dir="ltr"><div class="mw-content-ltr mw-parser-output" lang="de" dir="ltr"><p><b>SQL-Injection</b> (dt. <i>SQL-Einschleusung</i>) ist das Ausnutzen einer <a href="Sicherheitsl%C3%BCcke_(Software)" class="mw-redirect" title="Sicherheitslücke (Software)">Sicherheitslücke</a> in Zusammenhang mit <a href="SQL" title="SQL">SQL</a>-Datenbanken. Die Sicherheitslücke entsteht durch einen Programmierfehler in einem Programm, das auf die Datenbank zugreift. Durch diesen Programmierfehler kann ein Angreifer Datenbankbefehle einschleusen und abhängig vom Einzelfall weitere Daten aus der Datenbank auslesen, Daten unberechtigt ändern oder löschen oder sogar die Kontrolle über den kompletten Datenbankserver übernehmen.
</p>

<div class="mw-heading mw-heading2"><h2 id="Voraussetzungen">Voraussetzungen</h2></div>
<p>Ein erfolgreiches Ausnutzen einer SQL-Injection erfordert:
</p>
<ul><li>eine SQL-Datenbank, die angegriffen wird, zum Beispiel <a href="MySQL" title="MySQL">MySQL</a>, <a href="Microsoft_SQL_Server" title="Microsoft SQL Server">Microsoft SQL Server</a>, <a href="Db2" title="Db2">Db2</a></li>
<li>ein Anwendungsprogramm, in das Angreifer Daten eingeben können, zum Beispiel eine <a href="Login_(Informationstechnik)" title="Login (Informationstechnik)">Loginmaske</a>, eine Produktsuche in einem Onlineshop oder ein Kontaktformular im Web</li>
<li>dass das Anwendungsprogramm diese Daten an die Datenbank weiterreicht</li>
<li>einen Programmierfehler in dem Anwendungsprogramm, beim Weiterreichen der Daten</li></ul>
<p>Der Programmierfehler besteht darin, dass das Anwendungsprogramm die Eingabedaten nicht als reine Daten an die Datenbank weiterreicht, sondern aus diesen Daten die Datenbankabfrage erzeugt. Dadurch kann ein Angreifer versuchen, Teile der Datenbankabfrage gezielt zu steuern.
</p><p>In der Datenbankabfragesprache SQL haben einige Zeichen eine besondere Bedeutung, insbesondere:
</p>
<ul><li>der <a href="Apostroph" title="Apostroph">Apostroph</a>, um Textdaten zu umschließen</li>
<li>das <a href="Anf%C3%BChrungszeichen" title="Anführungszeichen">Anführungszeichen</a>, um Textdaten zu umschließen (nur einige Datenbanken)</li>
<li>der <a href="Umgekehrter_Schr%C3%A4gstrich" class="mw-redirect" title="Umgekehrter Schrägstrich">umgekehrte Schrägstrich</a> (Backslash), um das nachfolgende Zeichen nicht als besonderes Zeichen zu interpretieren</li>
<li>das <a href="Semikolon" title="Semikolon">Semikolon</a>, um einen Datenbankbefehl von dem nächsten Datenbankbefehl zu trennen</li>
<li>ein doppelter <a href="Bindestrich" class="mw-redirect" title="Bindestrich">Bindestrich</a>, um den Rest der Zeile zu ignorieren (<a href="Kommentar_(Programmierung)" title="Kommentar (Programmierung)">Kommentar</a>)</li></ul>
<p>Dokumentenorientierte <a href="NoSQL" title="NoSQL">NoSQL</a> Datenbanken können ebenfalls von diesem Sicherheitsproblem betroffen sein:
</p>
<ul><li>die geschweiften und eckigen <a href="Klammer_(Zeichen)#Klammern_im_Internationalen_Phonetischen_Alphabet" title="Klammer (Zeichen)">Klammern</a>, welche ein <a href="JSON" title="JSON">JSON</a> Objekt bzw. Array umschließen</li></ul>
<p>Diese Zeichen verwendet ein Angreifer gezielt, um den Angriff durchzuführen.
</p>
<div class="mw-heading mw-heading2"><h2 id="Beispiel">Beispiel</h2></div>
<p>Ein Beispiel für eine SQL-Abfrage, die in einem <a href="Redaktionssystem" title="Redaktionssystem">Redaktionssystem</a> nach Artikeln aus einer bestimmten Kategorie sucht, ist:
</p>
<dl><dd><div class="mw-highlight mw-highlight-lang-sql mw-content-ltr" dir="ltr"><pre><span></span><span class="k">SELECT</span><span class="w"> </span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="n">titel</span><span class="p">,</span><span class="w"> </span><span class="n">artikeltext</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">artikel</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">kategorie</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'gesuchte Kategorie'</span><span class="p">;</span>
</pre></div></dd></dl>
<p>Diese Abfrage hat folgende Bestandteile:
</p>
<ul><li>Die großgeschriebenen Wörter sind Schlüsselwörter in SQL und haben eine feste Bedeutung.</li>
<li>Die kleingeschriebenen Wörter sind die Namen von Tabellen, Zeilen oder Spalten in der Datenbank.</li>
<li>Text innerhalb von einfachen Anführungszeichen ist feststehender Text.</li></ul>
<p>Der Text „gesuchte Kategorie“ stellt hier nur einen Platzhalter dar, an dieser Stelle der Datenbankabfrage muss die jeweils gesuchte Kategorie eingetragen werden. Solange die gesuchte Kategorie keins der oben erwähnten Sonderzeichen enthält, könnte sie direkt in die Beispielabfrage eingesetzt werden.
</p><p>Wenn die gewünschte Kategorie jedoch zum Beispiel <a href="Rock_'n'_Roll" class="mw-redirect" title="Rock 'n' Roll">Rock_’n’_Roll</a> ist und damit einen Apostroph enthält, führt ein naives Ersetzen des Platzhalters zu dieser SQL-Abfrage:
</p>
<dl><dd><div class="mw-highlight mw-highlight-lang-sql mw-content-ltr" dir="ltr"><pre><span></span><span class="k">SELECT</span><span class="w"> </span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="n">titel</span><span class="p">,</span><span class="w"> </span><span class="n">artikeltext</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">artikel</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">kategorie</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'Rock '</span><span class="n">n</span><span class="s1">' Roll'</span><span class="p">;</span>
</pre></div></dd></dl>
<p>Auffällig ist hier die Doppelbedeutung des Apostroph: einerseits als Begrenzer, andererseits als wörtlich gemeintes Zeichen. Diese Doppelbedeutung ist für Menschen ersichtlich, aus Sicht der Datenbank ist diese Anfrage jedoch nicht sinnvoll interpretierbar, da die Abfrage als <code>kategorie = 'Rock '</code> interpretiert wird, gefolgt von einem Wort <code>n</code> und dem weiteren Text <code>' Roll'</code> in Apostrophen. Mit dem Wort <code>n</code> kann die Datenbank nichts anfangen und wird für diese Abfrage daher eine Fehlermeldung zurückgeben.
</p><p>Eine SQL-Injection besteht nun darin, dass der Angreifer durch gezielte Wahl der Eingabedaten die Datenbankabfrage so verändert, dass sie zwar noch eine gültige Struktur hat, aber eine andere Bedeutung. So führt zum Beispiel der scheinbar unsinnige Suchbegriff <code>asdfasdf' OR id &lt; 100 OR kategorie = 'sdfgsdfg</code> zu dieser Datenbankabfrage:
</p>
<dl><dd><div class="mw-highlight mw-highlight-lang-sql mw-content-ltr" dir="ltr"><pre><span></span><span class="k">SELECT</span><span class="w"> </span><span class="n">id</span><span class="p">,</span><span class="w"> </span><span class="n">titel</span><span class="p">,</span><span class="w"> </span><span class="n">artikeltext</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">artikel</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">kategorie</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'asdfasdf'</span><span class="w"> </span><span class="k">OR</span><span class="w"> </span><span class="n">id</span><span class="w"> </span><span class="o">&lt;</span><span class="w"> </span><span class="mi">100</span><span class="w"> </span><span class="k">OR</span><span class="w"> </span><span class="n">kategorie</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s1">'sdfgsdfg'</span><span class="p">;</span>
</pre></div></dd></dl>
<p>Diese Abfrage ist aus Sicht der Datenbank völlig korrekt, sie enthält 3 einzelne Bedingungen, von denen mindestens eine wahr sein muss. Die erste und dritte Bedingung haben in diesem Beispiel nur die Aufgabe, dass die SQL-Abfrage weiterhin <a href="Syntax#Syntax_formaler_Sprachen" title="Syntax">wohlgeformt</a> ist, und es ist unwahrscheinlich, dass es in der Datenbank tatsächlich Kategorien dieses Namens gibt. Daher bleibt als einzig relevante Bedingung <code>id &lt; 100</code> übrig. Aus der ursprünglichen SQL-Abfrage, die nur Artikel aus einer bestimmten Kategorie liefert, ist durch geschickte Wahl des Suchbegriffs eine strukturell andere SQL-Abfrage geworden, die nun die Artikel anhand ihrer ID sucht, unabhängig von der Kategorie.
</p><p>Durch diese geänderte SQL-Abfrage kann ein Angreifer möglicherweise Daten aus der Datenbank sehen, die nicht für ihn bestimmt sind. Durch andere gezielte Suchbegriffe kann der Angreifer möglicherweise Daten in der Datenbank ändern oder löschen, je nach Einzelfall.
</p><p>Der Programmierfehler besteht bei einer SQL-Injection darin, den Suchbegriff 1:1 in die Datenbankabfrage zu übernehmen, ohne die besondere Bedeutung des Apostroph und ähnlicher Zeichen zu berücksichtigen.
</p>
<div class="mw-heading mw-heading2"><h2 id="Vorgang">Vorgang</h2></div>
<div class="mw-heading mw-heading3"><h3 id="Veränderung_von_Daten"><span id="Ver.C3.A4nderung_von_Daten"></span>Veränderung von Daten</h3></div>
<p>Auf einem <a href="Webserver" title="Webserver">Webserver</a> befindet sich das Script find.cgi zum Anzeigen von Artikeln. Das Script akzeptiert den Parameter „ID“, welcher später Bestandteil der SQL-Abfrage wird. Folgende Tabelle soll dies illustrieren:
</p>
<table style="border: 1px solid #6688AA; background: #FFFFFF; padding: 1px;">
<tbody><tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">Erwarteter Aufruf
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/cgi-bin/find.cgi?ID=<i style="background-color:lightgreen;">42</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes SQL
</th>
<td><code>SELECT author, subject, text FROM artikel WHERE ID=<i style="background-color:lightgreen;">42</i>;</code>
</td></tr>
<tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">SQL-Injection
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/cgi-bin/find.cgi?ID=<i style="background-color:pink;">42;UPDATE+USER+SET+TYPE="admin"+WHERE+ID=23</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes SQL
</th>
<td><code>SELECT author, subject, text FROM artikel WHERE ID=<i style="background-color:pink;">42;UPDATE USER SET TYPE="admin" WHERE ID=23</i>;</code>
</td></tr></tbody></table>
<p>Dem Programm wird also ein zweiter SQL-Befehl untergeschoben, der die Benutzertabelle modifiziert.
</p>
<div class="mw-heading mw-heading3"><h3 id="Datenbank-Server_verändern"><span id="Datenbank-Server_ver.C3.A4ndern"></span>Datenbank-Server verändern</h3></div>
<p>Auf einem Webserver findet sich das Script search.aspx zum Suchen nach Webseiten. Das Script akzeptiert den Parameter „keyword“, dessen Wert später Bestandteil der SQL-Abfrage wird. Folgende Tabelle soll dies illustrieren:
</p>
<table style="border: 1px solid #6688AA; background: #FFFFFF; padding: 1px;">
<tbody><tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">Erwarteter Aufruf
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/search.aspx?keyword=<i style="background-color:lightgreen">sql</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes SQL
</th>
<td><code>SELECT url, title FROM myindex WHERE keyword LIKE '%<i style="background-color:lightgreen">sql</i>%'</code>
</td></tr>
<tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">SQL-Injection
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/search.aspx?keyword=<i style="background-color:pink">sql'+;GO+EXEC+cmdshell('shutdown+/s')+--</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes SQL
</th>
<td><code>SELECT url, title FROM myindex WHERE keyword LIKE '%<i style="background-color:pink">sql' ;GO EXEC cmdshell('shutdown /s') --</i>%'</code>
</td></tr></tbody></table>
<p>Hier wird der eigentlichen Abfrage ein weiterer Befehl angehängt. Die zwei Bindestriche <code>--</code> kommentieren das Hochkomma als Überbleibsel der eigentlichen Anfrage aus, womit es ignoriert wird. Die nun generierte Abfrage ermöglicht das Ausführen eines Windows-Prozesses, hier illustriert durch das erzwungene Herunterfahren des Servers (sofern der Prozess Administratorrechte hat). Aber auch Daten oder Ähnliches lassen sich dadurch erzeugen (am Beispiel Microsoft SQL Server).
</p>
<div class="mw-heading mw-heading3"><h3 id="Ausspähen_von_Daten"><span id="Aussp.C3.A4hen_von_Daten"></span>Ausspähen von Daten</h3></div>
<p>Auf manchen SQL-Implementationen ist die <code>UNION</code>-Klausel verfügbar. Diese erlaubt es, mehrere <code>SELECT</code>s gleichzeitig abzusetzen, die dann eine gemeinsame Ergebnismenge zurückliefern. Durch eine geschickt untergeschobene <code>UNION</code>-Klausel können beliebige Tabellen und Systemvariablen <a href="Aussp%C3%A4hen_von_Daten" title="Ausspähen von Daten">ausgespäht</a> werden.
</p>
<table style="border: 1px solid #6688AA; background: #FFFFFF; padding: 1px;">
<tbody><tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">Erwarteter Aufruf
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/cgi-bin/find.cgi?ID=<i style="background-color:lightgreen">42</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes SQL
</th>
<td><code>SELECT author, subject, text FROM artikel WHERE ID=<i style="background-color:lightgreen">42</i>;</code>
</td></tr>
<tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">SQL-Injection
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/cgi-bin/find.cgi?ID=<i style="background-color:pink">42+UNION+SELECT+login,+password,+'x'+FROM+user</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes SQL
</th>
<td><code>SELECT author, subject, text FROM artikel WHERE ID=<i style="background-color:pink">42 UNION SELECT login, password, 'x' FROM user</i>;</code>
</td></tr></tbody></table>
<p>Das <code>x</code> beim <code>UNION SELECT</code> ist nötig, weil alle mit <code>UNION</code> verknüpften <code>SELECT</code>s die gleiche Anzahl von Spalten haben müssen. Der Angreifer kann die Anzahl der Spalten herausfinden, indem er <code style="white-space:nowrap">ID=42 order by x--</code> anhängt. Wenn die Seite beispielsweise bei x&nbsp;=&nbsp;8 normal lädt, aber bei x&nbsp;=&nbsp;9 eine Fehlermeldung oder andere Seite zeigt, dann ist die Spaltenanzahl&nbsp;8.
</p><p>Ist der Datenbankserver fehlerhaft konfiguriert und hat beispielsweise ein aktuell mit der Datenbank verbundener Benutzer, über den die SQL-Injection abgesetzt werden soll, Zugriff auf Systemdatenbanken, so kann der Angreifer über eine einfache SQL-Syntax wie <code>Systemdatenbank.SystemtabelleMitTabellenAuflistung</code> auf die Systemtabellen zugreifen und sämtliche Tabellen einer bestimmten Datenbank auslesen. Dadurch kann er wichtige Informationen erhalten, um weitere Angriffe durchzuführen und tiefer in das System einzudringen.
</p><p>Bei MySQL-Datenbanksystemen werden diese Systeminformationen in der Datenbank <code>information_schema</code><sup id="cite_ref-1" class="reference"><a href="#cite_note-1"><span class="cite-bracket">[</span>1<span class="cite-bracket">]</span></a></sup> verwaltet. Das nachfolgende Beispiel zeigt, wie bei einer Abfrage mit 3 Ergebnisspalten die Struktur sämtlicher zugreifbarer Datenbanken in Erfahrung gebracht werden kann.
</p>
<table style="border: 1px solid #6688AA; background: #FFFFFF; padding: 1px;">
<tbody><tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">Erwarteter Aufruf
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/cgi-bin/find.cgi?ID=<i style="background-color:lightgreen">42</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes SQL
</th>
<td><code>SELECT author, subject, text FROM artikel WHERE ID=<i style="background-color:lightgreen">42</i>;</code>
</td></tr>
<tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">SQL-Injection
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/cgi-bin/find.cgi?ID=<i style="background-color:pink">42+UNION+SELECT+'Datenbank',+'Tabelle',+'Spalte'+<br>UNION+SELECT+table_schema,+table_name,+column_name+FROM+information_schema.columns+<br>WHERE+NOT+table_schema='information_schema';#%20</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes SQL
</th>
<td><code>SELECT author, subject, text FROM artikel WHERE ID=<i style="background-color:pink">42 UNION SELECT 'Datenbank', 'Tabelle', 'Spalte' <br>UNION SELECT table_schema, table_name, column_name FROM information_schema.columns <br>WHERE NOT table_schema='information_schema';#&nbsp;</i>;</code>
</td></tr></tbody></table>
<p>Einige Datenbanksysteme bieten weiterhin die Möglichkeit, Dateien über eine Anfrage zurückzugeben. Hierüber können in Kombination mit oben genannten Techniken und soweit der Pfad bekannt ist, beliebige Dateien, auf die der Datenbankprozess Zugriff hat, ausgelesen werden.
</p><p>Ein ähnlicher Aufruf in einer <a href="MongoDB" title="MongoDB">MongoDB</a> NoSQL Datenbank könnte so aussehen.
</p>
<table style="border: 1px solid #6688AA; background: #FFFFFF; padding: 1px;">
<tbody><tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">Erwarteter Aufruf
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/cgi-bin/find.cgi?ID=<i style="background-color:lightgreen">42</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes NoSQL
</th>
<td><code>db.users.find({ userID: <i style="background-color:lightgreen">42</i> });</code>
</td></tr>
<tr>
<th>&nbsp;
</th>
<th style="background:#ABCDEF">NoSQL-Injection
</th></tr>
<tr>
<th style="background:#ABCDEF">Aufruf
</th>
<td><code>http://webserver/cgi-bin/find.cgi?<i style="background-color:pink">ID['$ne']=</i></code>
</td></tr>
<tr>
<th style="background:#ABCDEF">Erzeugtes NoSQL
</th>
<td><code>db.users.find({ userID: <i style="background-color:pink">{ '$ne': undefined }</i> });</code>
</td></tr></tbody></table>
<p><code>$ne</code> ist der Operator für „ungleich“, die Abfrage gibt die Benutzer zurück, deren Benutzername nicht leer ist, d.&nbsp;h. alle Benutzer.
</p>
<div class="mw-heading mw-heading3"><h3 id="Einschleusen_von_beliebigem_Code">Einschleusen von beliebigem Code</h3></div>
<p>Eine weniger bekannte Variante stellt gleichzeitig die potenziell gefährlichste dar. Wenn der Datenbankserver die Kommandos <code>SELECT … INTO OUTFILE</code> beziehungsweise <code>SELECT … INTO DUMPFILE</code> unterstützt, können diese Kommandos dazu benutzt werden, Dateien auf dem <a href="Dateisystem" title="Dateisystem">Dateisystem</a> des Datenbankserver abzulegen. Theoretisch ist es dadurch möglich, falls das Bibliotheksverzeichnis des Betriebssystems oder des Datenbankservers für denselben beschreibbar ist (wenn dieser zum Beispiel als <a href="Root-Account" class="mw-redirect" title="Root-Account">root</a> läuft), einen beliebigen Code auf dem System auszuführen.
</p>
<div class="mw-heading mw-heading3"><h3 id="Zeitbasierte_Angriffe">Zeitbasierte Angriffe</h3></div>
<p>Wenn der Datenbankserver <a href="Benchmark" title="Benchmark">Benchmark</a>-Funktionen unterstützt, kann der Angreifer diese dazu nutzen, um Informationen über die Datenbankstruktur in Erfahrung zu bringen. In Verbindung mit dem if-Konstrukt sind der Kreativität des Angreifers kaum Grenzen gesetzt. Das Kopieren von Datenbankinhalten dauert allerdings wesentlich länger.
</p><p>Das folgende Beispiel benötigt auf einem <a href="MySQL" title="MySQL">MySQL</a>-Datenbankserver mehrere Sekunden, falls der gegenwärtige User <a href="Root_Account" class="mw-redirect" title="Root Account">root</a> ist:
</p>
<div class="mw-highlight mw-highlight-lang-sql mw-content-ltr" dir="ltr"><pre><span></span><span class="k">SELECT</span><span class="w"> </span><span class="k">IF</span><span class="p">(</span><span class="w"> </span><span class="k">USER</span><span class="p">()</span><span class="w"> </span><span class="k">LIKE</span><span class="w"> </span><span class="s1">'root@%'</span><span class="p">,</span><span class="w"> </span><span class="n">BENCHMARK</span><span class="p">(</span><span class="mi">100000</span><span class="p">,</span><span class="n">SHA1</span><span class="p">(</span><span class="s1">'test'</span><span class="p">)),</span><span class="w"> </span><span class="s1">'false'</span><span class="p">);</span>
</pre></div>
<p>Verwandt dazu sind Boolesche Angriffe, die durch Boolesche Abfragen versuchen, Datenbankinhalte zu extrahieren.
</p>
<div class="mw-heading mw-heading3"><h3 id="Erlangen_von_Administratorrechten">Erlangen von Administratorrechten</h3></div>
<p>Bei bestimmten Datenbankservern, wie dem <a href="Microsoft_SQL_Server" title="Microsoft SQL Server">Microsoft SQL Server</a> bis zur Version 2000, wurden <i>Stored Procedures</i> wie Xp_cmdshell automatisch angeboten, die unter anderem dazu missbraucht werden können, Kommandos mit den Rechten des SQL-Serverprogramms auszuführen. Neuere Versionen des Microsoft SQL Server haben diese Funktion standardmäßig deaktiviert. Diese Möglichkeit konnte dazu benutzt werden, um zum Beispiel eine <a href="Betriebssystem-Shell" class="mw-redirect" title="Betriebssystem-Shell">Shell</a> auf dem angegriffenen <a href="Computer" title="Computer">Rechner</a> zu starten.
</p>
<div class="mw-heading mw-heading3"><h3 id="Verwundbarkeiten_innerhalb_des_Datenbankservers">Verwundbarkeiten innerhalb des Datenbankservers</h3></div>
<p>Manchmal existieren Verwundbarkeiten auch innerhalb der Datenbanksoftware selbst. So erlaubte zum Beispiel die PHP-Funktion mysql_real_escape_string() im <a href="MySQL" title="MySQL">MySQL</a> Server einem Angreifer, SQL Injection-basierende Angriffe basierend auf Unicode-Zeichen selbst dann auszuführen, wenn die Benutzereingaben korrekt maskiert wurden. Dieser Fehler wurde in der Version 5.0.22 am 24. Mai 2006 behoben.
</p>
<div class="mw-heading mw-heading3"><h3 id="Blinde_SQL-Injection">Blinde SQL-Injection</h3></div>
<p>Von einer <i>blinden SQL-Injection</i> wird gesprochen, wenn ein Server keine deskriptive Fehlermeldung zurückliefert, aus der hervorgeht, ob der übergebene <a href="Abfragesprache" title="Abfragesprache">Query</a> erfolgreich ausgeführt wurde oder nicht. Anhand verschiedenster Kleinigkeiten wie etwa leicht unterschiedlicher Fehlermeldungen oder charakteristisch unterschiedlicher Antwortzeiten des Servers kann ein versierter Angreifer häufig dennoch feststellen, ob ein Query erfolgreich war oder einen Fehler zurückmeldet.
</p>
<div class="mw-heading mw-heading2"><h2 id="Gegenmaßnahmen"><span id="Gegenma.C3.9Fnahmen"></span>Gegenmaßnahmen</h2></div>
<p>Um SQL-Injections zu verhindern, dürfen vom Benutzer eingegebene Daten nicht ohne Weiteres in eine SQL-Anweisung eingebaut werden. Eingabedaten können auf die Eigenschaften erwarteter Werte geprüft werden. So bestehen deutsche Postleitzahlen beispielsweise nur aus Ziffern.
</p>
<div class="mw-heading mw-heading3"><h3 id="Grundidee_von_Prepared_Statements">Grundidee von Prepared Statements</h3></div>
<p>Der sicherste Weg ist jedoch, die Daten überhaupt vom SQL-Interpreter fernzuhalten.<sup id="cite_ref-2" class="reference"><a href="#cite_note-2"><span class="cite-bracket">[</span>2<span class="cite-bracket">]</span></a></sup> Dabei kann man auf das Kappen der Eingabe verzichten. <i>Die</i> Technik dazu sind gebundene Parameter in <a href="Prepared_Statement" title="Prepared Statement">Prepared Statements</a>. Dabei werden die Daten als Parameter an einen bereits kompilierten Befehl übergeben. Die Daten werden somit nicht interpretiert und eine SQL-Injection verhindert. <a href="Gespeicherte_Prozedur" title="Gespeicherte Prozedur">Stored Procedures</a> bieten dagegen keinen generellen Schutz vor SQL-Injection, insbesondere dann nicht, wenn der SQL-Code der Funktion nicht bekannt ist.
</p><p>Doch auch auf Seiten des Datenbankservers lassen sich Sicherheitsvorkehrungen treffen. So sollten die Benutzer, mit denen sich eine Webanwendung beim Datenbankserver authentifiziert, nur die Privilegien besitzen, die er tatsächlich benötigt. So können zumindest einige der möglichen Angriffe unwirksam werden.
</p><p>Hat ein Betreiber eines Webservers keine Kontrolle über die Anwendungen, kann durch Einsatz von <a href="Web_Application_Firewall" title="Web Application Firewall">Web Application Firewalls</a> (WAF) zumindest teilweise verhindert werden, dass SQL-Injection-Schwachstellen ausgenutzt werden können. Unabhängig von der Kontrolle über die Anwendungen kann ein Betreiber eines Webservers durch den gezielten Einsatz einer WAF die Sicherheit zusätzlich erhöhen, da viele WAFs neben abwehrenden auch prophylaktische Maßnahmen anbieten.
</p><p>Es ist nicht schwer, bestehende Programme so umzubauen, dass SQL-Injections nicht mehr möglich sind. Das hauptsächliche Problem der meisten Programmierer ist fehlendes Wissen über diese Art von Angriffen. Nachfolgend einige Beispiele, um die Angriffe abzuwehren.
</p><p>Die naive, aber falsche Idee, eine SQL-Abfrage mit beliebigen Eingabedaten anzureichern, sieht in den meisten Programmiersprachen so aus:
</p>
<div class="mw-highlight mw-highlight-lang-python3 mw-content-ltr" dir="ltr"><pre><span></span><span class="c1"># gefährlicher Code, enthält die Sicherheitslücke SQL-Injection</span>
<span class="n">sql</span> <span class="o">=</span> <span class="s2">"SELECT spalte1 FROM tabelle WHERE spalte2 = '"</span> <span class="o">+</span> <span class="n">eingabedaten</span> <span class="o">+</span> <span class="s2">"';"</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">sql</span><span class="p">)</span>
</pre></div>
<p>Die doppelten Anführungszeichen gehören hier zur Programmiersprache, die einfachen Anführungszeichen gehören zu SQL. Wenn die Eingabedaten selbst auch einfache Anführungszeichen enthalten können, ist eine SQL-Injection möglich. Um das zu verhindern, ist die Idee, die SQL-Anfrage und die Daten zu trennen. Das <code>:eingabedaten</code> im folgenden Code ist ein Platzhalter für die eigentlichen Eingabedaten. Diese werden in einem zweiten Schritt bei der Abfrage mittels <code>db.query</code> an die Datenbank übergeben. Die Trennung von SQL und Eingabedaten verhindert eine SQL-Injection.
</p>
<div class="mw-highlight mw-highlight-lang-python3 mw-content-ltr" dir="ltr"><pre><span></span><span class="n">sql</span> <span class="o">=</span> <span class="s2">"SELECT spalte1 FROM tabelle WHERE spalte2 = :eingabedaten;"</span>
<span class="n">query</span> <span class="o">=</span> <span class="n">db</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">sql</span><span class="p">,</span> <span class="n">eingabedaten</span><span class="o">=</span><span class="n">eingabedaten</span><span class="p">)</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Python">Python</h3></div>
<p>In Python gibt es mehrere Möglichkeiten, mit einer Datenbank zu kommunizieren. Eine davon ist <a href="SQLAlchemy" title="SQLAlchemy">SQLAlchemy</a>. Um hierbei SQL-Injection zu entgehen, sollte man rohe SQL-Befehle vermeiden, sofern diese durch Form- oder URL Anfragen manipuliert werden könnten. Nachfolgend ist ein solches Beispiel zu sehen:
</p>
<div class="mw-highlight mw-highlight-lang-python3 mw-content-ltr" dir="ltr"><pre><span></span><span class="n">db</span><span class="o">.</span><span class="n">engine</span><span class="o">.</span><span class="n">execute</span><span class="p">(</span><span class="s2">"SELECT * FROM table"</span><span class="p">)</span>
</pre></div>
<p>Stattdessen wird dazu geraten die internen Funktionen und Methoden von SQLAlchemy zu nutzen, wie z.&nbsp;B. die Folgenden:<sup id="cite_ref-3" class="reference"><a href="#cite_note-3"><span class="cite-bracket">[</span>3<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-highlight mw-highlight-lang-python3 mw-content-ltr" dir="ltr"><pre><span></span><span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Order</span><span class="p">)</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="n">order_id</span><span class="p">)</span>
<span class="n">session</span><span class="o">.</span><span class="n">query</span><span class="p">(</span><span class="n">Order</span><span class="p">)</span><span class="o">.</span><span class="n">filter</span><span class="p">(</span><span class="n">Order</span><span class="o">.</span><span class="n">status</span> <span class="o">==</span> <span class="s1">'active'</span><span class="p">)</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Visual_Basic_(ADOdb)"><span id="Visual_Basic_.28ADOdb.29"></span>Visual Basic (ADOdb)</h3></div>
<p>In <a href="Visual_Basic_Classic" title="Visual Basic Classic">Visual Basic</a> gibt es einfache <i>Command</i>-Objekte, mit denen diese Probleme vermieden werden können.
</p><p>Anstatt
</p>
<div class="mw-highlight mw-highlight-lang-vbnet mw-content-ltr" dir="ltr"><pre><span></span><span class="n">cn</span><span class="p">.</span><span class="n">Execute</span><span class="w"> </span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 = '"</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="n">spalte2Wert</span><span class="w"> </span><span class="o">&amp;</span><span class="w"> </span><span class="s">"'"</span>
</pre></div>
<p>sollte Folgendes verwendet werden:
</p>
<div class="mw-highlight mw-highlight-lang-vbnet mw-content-ltr" dir="ltr"><pre><span></span><span class="k">Dim</span><span class="w"> </span><span class="n">cmd</span><span class="w"> </span><span class="ow">As</span><span class="w"> </span><span class="n">ADODB</span><span class="p">.</span><span class="n">Command</span><span class="p">,</span><span class="w"> </span><span class="n">rs</span><span class="w"> </span><span class="ow">as</span><span class="w"> </span><span class="n">ADODB</span><span class="p">.</span><span class="n">Recordset</span>
<span class="k">With</span><span class="w"> </span><span class="n">cmd</span>
<span class="w"> </span><span class="k">Set</span><span class="w"> </span><span class="p">.</span><span class="n">ActiveConnection</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">cn</span>
<span class="w"> </span><span class="k">Set</span><span class="w"> </span><span class="p">.</span><span class="n">CommandType</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">adCmdText</span>
<span class="w"> </span><span class="p">.</span><span class="n">CommandText</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 =&nbsp;?"</span>
<span class="w"> </span><span class="p">.</span><span class="n">Parameters</span><span class="p">.</span><span class="n">Append</span><span class="w"> </span><span class="p">.</span><span class="n">CreateParameter</span><span class="p">(</span><span class="s">"paramSp2"</span><span class="p">,</span><span class="w"> </span><span class="n">adVarChar</span><span class="p">,</span><span class="w"> </span><span class="n">adParamInput</span><span class="p">,</span><span class="w"> </span><span class="mi">25</span><span class="p">,</span><span class="w"> </span><span class="n">spalte2Wert</span><span class="p">)</span><span class="w"> </span><span class="c">'25 ist die max. länge</span>
<span class="w"> </span><span class="k">Set</span><span class="w"> </span><span class="n">rs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">.</span><span class="n">Execute</span>
<span class="k">End</span><span class="w"> </span><span class="k">With</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Delphi">Delphi</h3></div>
<p>Seit der BDE kennen die Querys Parameter. Die Syntax ist bei verschiedenen Komponentensammlungen nicht immer identisch aber ähnlich.
</p><p>Anstatt …
</p>
<div class="mw-highlight mw-highlight-lang-delphi mw-content-ltr" dir="ltr"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="nc">TDatabase</span><span class="o">.</span><span class="nf">GetData</span><span class="p">(</span><span class="n">ParameterID</span><span class="o">:</span><span class="w"> </span><span class="kt">Integer</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">Integer</span><span class="o">;</span>
<span class="k">var</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">:</span><span class="w"> </span><span class="n">TQuery</span><span class="o">;</span>
<span class="k">begin</span>
<span class="w"> </span><span class="bp">Result</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="o">;</span>
<span class="w"> </span><span class="n">Qry</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="n">TQuery</span><span class="o">.</span><span class="n">Create</span><span class="o">;</span>
<span class="w"> </span><span class="k">try</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">SQL</span><span class="o">.</span><span class="n">Text</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">'SELECT F_DATA FROM T_BLUBB WHERE ID = '</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="nb">IntToStr</span><span class="p">(</span><span class="n">ParameterID</span><span class="p">)</span><span class="o">;</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">Open</span><span class="o">;</span>
<span class="w"> </span><span class="bp">Result</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">FieldByName</span><span class="p">(</span><span class="s">'F_DATA'</span><span class="p">)</span><span class="o">.</span><span class="n">AsInteger</span><span class="o">;</span>
<span class="w"> </span><span class="k">finally</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">Free</span><span class="o">;</span>
<span class="w"> </span><span class="k">end</span><span class="o">;</span>
<span class="k">end</span><span class="o">;</span>
</pre></div>
<p>… sollte definitiv mit Parametern gearbeitet werden:
</p>
<div class="mw-highlight mw-highlight-lang-delphi mw-content-ltr" dir="ltr"><pre><span></span><span class="k">function</span><span class="w"> </span><span class="nc">TDatabase</span><span class="o">.</span><span class="nf">GetData</span><span class="p">(</span><span class="n">ParameterID</span><span class="o">:</span><span class="w"> </span><span class="kt">Integer</span><span class="p">)</span><span class="o">:</span><span class="w"> </span><span class="kt">Integer</span><span class="o">;</span>
<span class="k">var</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">:</span><span class="w"> </span><span class="n">TQuery</span><span class="o">;</span>
<span class="k">begin</span>
<span class="w"> </span><span class="bp">Result</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="mi">0</span><span class="o">;</span>
<span class="w"> </span><span class="n">Qry</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="n">TQuery</span><span class="o">.</span><span class="n">Create</span><span class="o">;</span>
<span class="w"> </span><span class="k">try</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">SQL</span><span class="o">.</span><span class="n">Text</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="s">'SELECT F_DATA FROM T_BLUBB WHERE ID = :PI'</span><span class="o">;</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">ParamByName</span><span class="p">(</span><span class="s">'PI'</span><span class="p">)</span><span class="o">.</span><span class="n">AsInteger</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="n">ParameterID</span><span class="o">;</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">Open</span><span class="o">;</span>
<span class="w"> </span><span class="bp">Result</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">FieldByName</span><span class="p">(</span><span class="s">'F_DATA'</span><span class="p">)</span><span class="o">.</span><span class="n">AsInteger</span><span class="o">;</span>
<span class="w"> </span><span class="k">finally</span>
<span class="w"> </span><span class="n">Qry</span><span class="o">.</span><span class="n">Free</span><span class="o">;</span>
<span class="w"> </span><span class="k">end</span><span class="o">;</span>
<span class="k">end</span><span class="o">;</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Microsoft_.NET_Framework_–_C#_(ADO.NET)"><span id="Microsoft_.NET_Framework_.E2.80.93_C.23_.28ADO.NET.29"></span>Microsoft .NET Framework – C# (ADO.NET)</h3></div>
<p>Im <a href=".Net-Framework" title=".Net-Framework">.Net-Framework</a> gibt es einfache Objekte, mit denen solche Probleme umgangen werden können.
</p><p>Anstatt
</p>
<div class="mw-highlight mw-highlight-lang-csharp mw-content-ltr" dir="ltr"><pre><span></span><span class="n">SqlCommand</span><span class="w"> </span><span class="n">cmd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">SqlCommand</span><span class="p">(</span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 = '"</span>
<span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">spalte2Wert</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">"';"</span><span class="p">);</span>
</pre></div>
<p>sollte Folgendes verwendet werden:
</p>
<div class="mw-highlight mw-highlight-lang-csharp mw-content-ltr" dir="ltr"><pre><span></span><span class="kt">string</span><span class="w"> </span><span class="n">spalte2Wert</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">"Mein Wert"</span><span class="p">;</span>
<span class="n">SqlCommand</span><span class="w"> </span><span class="n">cmd</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">new</span><span class="w"> </span><span class="n">SqlCommand</span><span class="p">(</span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 = @spalte2Wert;"</span><span class="p">);</span>
<span class="n">cmd</span><span class="p">.</span><span class="n">Parameters</span><span class="p">.</span><span class="n">AddWithValue</span><span class="p">(</span><span class="s">"@spalte2Wert"</span><span class="p">,</span><span class="w"> </span><span class="n">spalte2Wert</span><span class="p">);</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="Java_(JDBC)"><span id="Java_.28JDBC.29"></span>Java (JDBC)</h3></div>
<p>Eine SQL-Injection kann leicht durch eine bereits vorhandene Funktion verhindert werden. In <a href="Java_(Programmiersprache)" title="Java (Programmiersprache)">Java</a> wird zu diesem Zweck die PreparedStatement-Klasse verwendet (<a href="Java_Database_Connectivity" title="Java Database Connectivity">JDBC</a>-Technologie) und die Daten unsicherer Herkunft werden als getrennte Parameter übergeben. Um die Daten von der SQL-Anweisung zu trennen, wird der Platzhalter „?“ verwendet.
</p><p>Anstatt
</p>
<div class="mw-highlight mw-highlight-lang-java mw-content-ltr" dir="ltr"><pre><span></span><span class="n">Statement</span><span class="w"> </span><span class="n">stmt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">con</span><span class="p">.</span><span class="na">createStatement</span><span class="p">();</span>
<span class="n">ResultSet</span><span class="w"> </span><span class="n">rset</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">stmt</span><span class="p">.</span><span class="na">executeQuery</span><span class="p">(</span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 = '"</span>
<span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="n">spalte2Wert</span><span class="w"> </span><span class="o">+</span><span class="w"> </span><span class="s">"';"</span><span class="p">);</span>
</pre></div>
<p>sollte Folgendes verwendet werden:
</p>
<div class="mw-highlight mw-highlight-lang-java mw-content-ltr" dir="ltr"><pre><span></span><span class="n">PreparedStatement</span><span class="w"> </span><span class="n">pstmt</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">con</span><span class="p">.</span><span class="na">prepareStatement</span><span class="p">(</span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 =&nbsp;?"</span><span class="p">);</span>
<span class="n">pstmt</span><span class="p">.</span><span class="na">setString</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span><span class="w"> </span><span class="n">spalte2Wert</span><span class="p">);</span>
<span class="n">ResultSet</span><span class="w"> </span><span class="n">rset</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">pstmt</span><span class="p">.</span><span class="na">executeQuery</span><span class="p">();</span>
</pre></div>
<p>Der Mehraufwand an Schreibarbeit durch die Verwendung der PreparedStatement-Klasse kann sich außerdem durch einen Performancegewinn auszahlen, wenn das Programm das PreparedStatement-Objekt mehrfach verwendet.
</p>
<div class="mw-heading mw-heading3"><h3 id="PHP">PHP</h3></div>
<p>In <a href="PHP" title="PHP">PHP</a> steht für Datenbankzugriffe die Bibliothek <a href="PHP_Data_Objects" title="PHP Data Objects">PHP Data Objects</a> zur Verfügung.
</p><p>Beispiel ohne Prepared Statement:
</p>
<div class="mw-highlight mw-highlight-lang-php mw-content-ltr" dir="ltr"><pre><span></span><span class="nv">$dbh</span><span class="o">-&gt;</span><span class="na">exec</span><span class="p">(</span><span class="s2">"INSERT INTO REGISTRY (name, value)</span>
<span class="s2"> VALUES ("</span><span class="o">.</span><span class="nv">$dbh</span><span class="o">-&gt;</span><span class="na">quote</span><span class="p">(</span><span class="nv">$name</span><span class="p">,</span><span class="nx">PDO</span><span class="o">::</span><span class="na">PARAM_STR</span><span class="p">)</span><span class="o">.</span><span class="s2">", "</span><span class="o">.</span><span class="nv">$dbh</span><span class="o">-&gt;</span><span class="na">quote</span><span class="p">(</span><span class="nv">$value</span><span class="p">,</span><span class="nx">PDO</span><span class="o">::</span><span class="na">PARAM_INT</span><span class="p">)</span><span class="o">.</span><span class="s2">")"</span><span class="p">);</span>
</pre></div>
<p>Beispiel mit Prepared Statement:
</p>
<div class="mw-highlight mw-highlight-lang-php mw-content-ltr" dir="ltr"><pre><span></span><span class="nv">$stmt</span> <span class="o">=</span> <span class="nv">$dbh</span><span class="o">-&gt;</span><span class="na">prepare</span><span class="p">(</span><span class="s2">"INSERT INTO REGISTRY (name, value) VALUES (:name, :value)"</span><span class="p">);</span>
<span class="nv">$stmt</span><span class="o">-&gt;</span><span class="na">bindParam</span><span class="p">(</span><span class="s1">':name'</span><span class="p">,</span> <span class="nv">$name</span><span class="p">);</span>
<span class="nv">$stmt</span><span class="o">-&gt;</span><span class="na">bindParam</span><span class="p">(</span><span class="s1">':value'</span><span class="p">,</span> <span class="nv">$value</span><span class="p">);</span>
</pre></div>
<p>Bis zur PHP-Version 5.3 gab es die Konfigurationsoption „magic_quotes_gpc“. War diese auf „on“ gestellt, wurden von außen kommende Benutzereingaben automatisch maskiert. Manche Skripte nutzen Funktionen wie etwa <code>addslashes()</code><sup id="cite_ref-4" class="reference"><a href="#cite_note-4"><span class="cite-bracket">[</span>4<span class="cite-bracket">]</span></a></sup> oder <code>mysql_real_escape_string()</code><sup id="cite_ref-5" class="reference"><a href="#cite_note-5"><span class="cite-bracket">[</span>5<span class="cite-bracket">]</span></a></sup>. Das heißt, dass bereits allen relevanten Zeichen in den Benutzereingaben durch so genannte Magic Quotes<sup id="cite_ref-6" class="reference"><a href="#cite_note-6"><span class="cite-bracket">[</span>6<span class="cite-bracket">]</span></a></sup> ein <a href="Backslash" title="Backslash">Backslash</a> vorangestellt wurde und nun durch die Escape-Funktion erneut ein Backslash vorangestellt wird. Somit werden die Benutzereingaben verfälscht und man erhält beispielsweise anstatt eines einfachen Anführungszeichens ein Anführungszeichen mit vorangestelltem Backslash (<code>\"</code>). Auch aus Gründen der <a href="Plattformunabh%C3%A4ngigkeit" title="Plattformunabhängigkeit">Portabilität</a> sollte bei der Entwicklung von Anwendungen auf diese Einstellung verzichtet und stattdessen alle Eingaben manuell validiert und maskiert werden, da nicht davon ausgegangen werden kann, dass auf allen Systemen dieselben Einstellungen vorherrschen oder möglich sind. Darüber hinaus sollte <code>addSlashes()</code> nicht zum Maskieren von Datenbank-Eingaben benutzt werden, da es keine ausreichende Sicherheit gegenüber <code>mysql_real_escape_string()</code> gewährleistet.<sup id="cite_ref-7" class="reference"><a href="#cite_note-7"><span class="cite-bracket">[</span>7<span class="cite-bracket">]</span></a></sup>
</p><p>Nach der PHP-Version 5.3 wurde <code>mysql_real_escape_string()</code> durch <a href="MySQLi" title="MySQLi">MySQLi</a> ersetzt. Ab der Version 7.0 ist <code>mysql_real_escape_string()</code> nicht mehr verfügbar. Ab PHP 7.x heißt die Funktion <code>mysqli_real_escape_string()</code>.
</p><p>Grundsätzlich sind auch in puncto Sicherheit immer Prepared Statements vorzuziehen.
</p>
<div class="mw-heading mw-heading3"><h3 id="Perl">Perl</h3></div>
<p>Mit dem datenbankunabhängigen <a href="Modul_(Software)" title="Modul (Software)">Datenbankmodul</a> <a href="Perl-DBI" title="Perl-DBI">DBI</a>, welches normalerweise in <a href="Perl_(Programmiersprache)" title="Perl (Programmiersprache)">Perl</a> verwendet wird:
</p><p>Anstatt
</p>
<div class="mw-highlight mw-highlight-lang-perl mw-content-ltr" dir="ltr"><pre><span></span><span class="nv">$arrayref</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$databasehandle</span><span class="o">-&gt;</span><span class="n">selectall_arrayref</span><span class="p">(</span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 = $spalte2Wert"</span><span class="p">);</span>
</pre></div>
<p>sollte Folgendes verwendet werden:
</p>
<div class="mw-highlight mw-highlight-lang-perl mw-content-ltr" dir="ltr"><pre><span></span><span class="nv">$arrayref</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$databasehandle</span><span class="o">-&gt;</span><span class="n">selectall_arrayref</span><span class="p">(</span><span class="s">'SELECT spalte1 FROM tabelle WHERE spalte2 =&nbsp;?'</span><span class="p">,{},</span><span class="nv">$spalte2Wert</span><span class="p">);</span>
</pre></div>
<p>Perls DBI-Modul unterstützt außerdem eine „prepare“-Syntax ähnlich der aus dem Java-Beispiel.
</p>
<div class="mw-highlight mw-highlight-lang-perl mw-content-ltr" dir="ltr"><pre><span></span><span class="nv">$statementhandle</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$databasehandle</span><span class="o">-&gt;</span><span class="n">prepare</span><span class="p">(</span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 =&nbsp;?"</span><span class="p">);</span>
<span class="nv">$returnvalue</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$statementhandle</span><span class="o">-&gt;</span><span class="n">execute</span><span class="p">(</span><span class="w"> </span><span class="nv">$spalte2Wert</span><span class="w"> </span><span class="p">);</span>
</pre></div>
<p>Alternativ können über das Datenbankhandle auch Eingabe-Werte sicher maskiert werden. Dabei achtet der DB-Treiber auf die für diese Datenbank typischen Sonderzeichen. Der Programmierer muss keine tiefergehenden Kenntnisse darüber haben.
</p>
<div class="mw-highlight mw-highlight-lang-perl mw-content-ltr" dir="ltr"><pre><span></span><span class="nv">$arrayref</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nv">$databasehandle</span><span class="o">-&gt;</span><span class="n">selectall_arrayref</span><span class="p">(</span><span class="s">"SELECT spalte1 FROM tabelle WHERE spalte2 = "</span><span class="w"> </span><span class="o">.</span>
<span class="w"> </span><span class="nv">$databasehandle</span><span class="o">-&gt;</span><span class="n">quote</span><span class="p">(</span><span class="nv">$spalte2Wert</span><span class="p">)</span><span class="w"> </span><span class="p">);</span>
</pre></div>
<p>Im sogenannten „taint mode“, der skriptweit mit dem Parameter <span style="font-family:monospace;">-T</span> aktiviert werden kann, verwendet Perl starke Heuristiken, um nur sichere Zugriffe zu erlauben. Zeichenketten, die vom Benutzer übergebene Parameter enthalten, werden zunächst als „unsicher“ behandelt, bis die Daten explizit validiert wurden, und dürfen vorher nicht in unsicheren Befehlen verwendet werden.
</p>
<div class="mw-heading mw-heading3"><h3 id="ColdFusion_Markup_Language">ColdFusion Markup Language</h3></div>
<p>Unter <a href="ColdFusion" title="ColdFusion">ColdFusion</a> kann das <code>&lt;cfqueryparam&gt;</code>-Tag verwendet werden, welches sämtliche notwendigen
Validierungen übernimmt:<sup id="cite_ref-8" class="reference"><a href="#cite_note-8"><span class="cite-bracket">[</span>8<span class="cite-bracket">]</span></a></sup>
</p>
<div class="mw-highlight mw-highlight-lang-cfm mw-content-ltr" dir="ltr"><pre><span></span> SELECT * FROM courses WHERE Course_ID =
<span class="p">&lt;</span><span class="nt">cfqueryparam</span> <span class="na">value </span><span class="o">=</span> <span class="s">"#Course_ID#"</span> <span class="na">CFSQLType </span><span class="o">=</span> <span class="s">"CF_SQL_INTEGER"</span><span class="p">&gt;</span>
</pre></div>
<div class="mw-heading mw-heading3"><h3 id="MS-SQL">MS-SQL</h3></div>
<p>Über parametrisierte Kommandos kann die Datenbank vor SQL-Injections geschützt werden:
</p>
<div class="mw-highlight mw-highlight-lang-sql mw-content-ltr" dir="ltr"><pre><span></span><span class="k">SELECT</span><span class="w"> </span><span class="k">COUNT</span><span class="p">(</span><span class="o">*</span><span class="p">)</span><span class="w"> </span><span class="k">FROM</span><span class="w"> </span><span class="n">Users</span><span class="w"> </span><span class="k">WHERE</span><span class="w"> </span><span class="n">UserName</span><span class="o">=?</span><span class="w"> </span><span class="k">AND</span><span class="w"> </span><span class="n">UserPasswordHash</span><span class="o">=?</span>
</pre></div>
<div class="mw-heading mw-heading2"><h2 id="Siehe_auch">Siehe auch</h2></div>
<ul><li><a href="Sicherheit_von_Webanwendungen" title="Sicherheit von Webanwendungen">Sicherheit von Webanwendungen</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="Weblinks">Weblinks</h2></div>
<ul><li><a rel="nofollow" class="external text" href="http://www.erich-kachel.de/?p=223">SQL-Injections – Analyse</a></li>
<li><a rel="nofollow" class="external text" href="http://www.derkeiler.com/Mailing-Lists/securityfocus/secprog/2001-07/0001.html">Abusing Poor Programming Techniques in Webserver Scripts via SQL Injection</a> (englisch)</li>
<li><a rel="nofollow" class="external text" href="https://www.bsi.bund.de/SharedDocs/Downloads/DE/BSI/Publikationen/Studien/WebSec/WebSec.pdf?__blob=publicationFile&amp;v=1">Sicherheit von Webanwendungen: Maßnahmenkatalog und Best Practices</a> (PDF; 805 kB) <a href="Bundesamt_f%C3%BCr_Sicherheit_in_der_Informationstechnik" title="Bundesamt für Sicherheit in der Informationstechnik">Bundesamt für Sicherheit in der Informationstechnik</a> (BSI)</li>
<li><a rel="nofollow" class="external text" href="http://www.webappsec.org/projects/threat/v1/WASC-TC-v1_0.de.pdf">Web Security Threat Classification</a> (PDF, 432 kB)</li>
<li>Steve Friedl: <a rel="nofollow" class="external text" href="http://unixwiz.net/techtips/sql-injection.html"><i>SQL Injection Attacks by Example</i>.</a></li>
<li><a rel="nofollow" class="external text" href="https://www.yekta-it.de/sites/default/files/pdf/Advanced-SQL-Injection-in-MySQL-GERMAN.pdf">Advanced SQL Injection in MySQL</a> (PDF; 935 kB)</li>
<li><a rel="nofollow" class="external text" href="https://xkcd.com/327/">SQL-Injection im Comic xkcd</a> (<a href="Xkcd" title="Xkcd">xkcd.com</a>)</li>
<li><a rel="nofollow" class="external text" href="https://www.youtube.com/watch?v=8vM8b2P5uOo&amp;list=PL4aVL6eAcvHnfoZ0aVKzQFVA0AZK7bn2f">SQLi: Videos zur Durchführung und Gegenmaßnahmen</a></li></ul>
<div class="mw-heading mw-heading2"><h2 id="Einzelnachweise_und_Ressourcen">Einzelnachweise und Ressourcen</h2></div>
<ol class="references">
<li id="cite_note-1"><span class="mw-cite-backlink"><a href="#cite_ref-1">↑</a></span> <span class="reference-text"><a rel="nofollow" class="external text" href="http://dev.mysql.com/doc/refman/5.1/en/information-schema.html">Die Datenbank <span style="font-family:monospace;">INFORMATION_SCHEMA</span>.</a> MySQL 5.1 Referenzhandbuch, Kapitel 20</span>
</li>
<li id="cite_note-2"><span class="mw-cite-backlink"><a href="#cite_ref-2">↑</a></span> <span class="reference-text"><span class="cite"><a rel="nofollow" class="external text" href="https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/SQL_Injection_Prevention_Cheat_Sheet.md"><i>SQL_Injection_Prevention_Cheat_Sheet.md.</i></a><span class="Abrufdatum"> Abgerufen am 24.&nbsp;Oktober 2019</span>.</span><span style="display: none;" class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Fde.wikipedia.org%3ASQL-Injection&amp;rft.title=SQL_Injection_Prevention_Cheat_Sheet.md&amp;rft.description=SQL_Injection_Prevention_Cheat_Sheet.md&amp;rft.identifier=https%3A%2F%2Fgithub.com%2FOWASP%2FCheatSheetSeries%2Fblob%2Fmaster%2Fcheatsheets%2FSQL_Injection_Prevention_Cheat_Sheet.md&amp;rft.date=">&nbsp;</span></span>
</li>
<li id="cite_note-3"><span class="mw-cite-backlink"><a href="#cite_ref-3">↑</a></span> <span class="reference-text"><span class="cite"><a rel="nofollow" class="external text" href="http://pajhome.org.uk/blog/10_reasons_to_love_sqlalchemy.html"><i>10 Reasons to love SQLAlchemy.</i></a> In: <i>pajhome.org.uk.</i><span class="Abrufdatum"> Abgerufen am 20.&nbsp;Dezember 2016</span>.</span><span style="display: none;" class="Z3988" title="ctx_ver=Z39.88-2004&amp;rft_val_fmt=info%3Aofi%2Ffmt%3Akev%3Amtx%3Adc&amp;rfr_id=info%3Asid%2Fde.wikipedia.org%3ASQL-Injection&amp;rft.title=10+Reasons+to+love+SQLAlchemy&amp;rft.description=10+Reasons+to+love+SQLAlchemy&amp;rft.identifier=http%3A%2F%2Fpajhome.org.uk%2Fblog%2F10_reasons_to_love_sqlalchemy.html">&nbsp;</span></span>
</li>
<li id="cite_note-4"><span class="mw-cite-backlink"><a href="#cite_ref-4">↑</a></span> <span class="reference-text"><a rel="nofollow" class="external text" href="http://de.php.net/manual/de/function.addslashes.php">addslashes</a> PHP Manual</span>
</li>
<li id="cite_note-5"><span class="mw-cite-backlink"><a href="#cite_ref-5">↑</a></span> <span class="reference-text"><a rel="nofollow" class="external text" href="http://de.php.net/manual/de/function.mysql-real-escape-string.php">mysql_real_escape_string</a> PHP Manual</span>
</li>
<li id="cite_note-6"><span class="mw-cite-backlink"><a href="#cite_ref-6">↑</a></span> <span class="reference-text"><style data-mw-deduplicate="TemplateStyles:r261891140">
/* start https://de.wikipedia.org/ */


.mw-parser-output .webarchiv-memento a{color:inherit}


/* end https://de.wikipedia.org/ */
</style><a rel="nofollow" class="external text" href="https://web.archive.org/web/20210103050704/http://www.php.net/manual/de/security.magicquotes.php">Magic Quotes</a> (<span class="webarchiv-memento"><a href="Webarchivierung#Begrifflichkeiten" title="Webarchivierung">Memento</a></span> des <style data-mw-deduplicate="TemplateStyles:r250917974">
/* start https://de.wikipedia.org/ */


.mw-parser-output .dewiki-iconexternal>a{background-position:center right!important;background-repeat:no-repeat!important}body.skin-minerva .mw-parser-output .dewiki-iconexternal>a{background-image:url("./_mw_/OOjs_UI_icon_external-link-ltr-progressive.svg")!important;background-size:10px!important;padding-right:13px!important}body.skin-timeless .mw-parser-output .dewiki-iconexternal>a,body.skin-monobook .mw-parser-output .dewiki-iconexternal>a{background-image:url("./_mw_/MediaWiki_external_link_icon.svg")!important;padding-right:13px!important}body.skin-vector .mw-parser-output .dewiki-iconexternal>a{background-image:url("./_mw_/Link.ernal-small-ltr-progressive.svg")!important;background-size:0.857em!important;padding-right:1em!important}


/* end https://de.wikipedia.org/ */
</style><span class="dewiki-iconexternal"><a class="external text" href="https://redirecter.toolforge.org/?url=http%3A%2F%2Fwww.php.net%2Fmanual%2Fde%2Fsecurity.magicquotes.php">Originals</a></span> vom 3. Januar 2021 im <i><a href="Internet_Archive" title="Internet Archive">Internet Archive</a></i>) <small class="archiv-bot"><span class="wp_boppel noviewer" aria-hidden="true" role="presentation"><span typeof="mw:File"><span title="i"></span></span></span>&nbsp;<b>Info:</b> Der Archivlink wurde automatisch eingesetzt und noch nicht geprüft. Bitte prüfe Original- und Archivlink gemäß Anleitung und entferne dann diesen Hinweis.</small><span style="display:none"><a rel="nofollow" class="external text" href="http://IABotmemento.invalid/http://www.php.net/manual/de/security.magicquotes.php">@1</a></span><span style="display:none"><a rel="nofollow" class="external text" href="http://www.php.net/manual/de/security.magicquotes.php">@2</a></span><span style="display:none">Vorlage:Webachiv/IABot/www.php.net</span> PHP Manual</span>
</li>
<li id="cite_note-7"><span class="mw-cite-backlink"><a href="#cite_ref-7">↑</a></span> <span class="reference-text">Chris Shiflett: <a rel="nofollow" class="external text" href="http://shiflett.org/blog/2006/jan/addslashes-versus-mysql-real-escape-string">addslashes() Versus mysql_real_escape_string()</a> (englisch)</span>
</li>
<li id="cite_note-8"><span class="mw-cite-backlink"><a href="#cite_ref-8">↑</a></span> <span class="reference-text"><a rel="nofollow" class="external text" href="https://web.archive.org/web/20061124152957/http://livedocs.macromedia.com/coldfusion/7/htmldocs/00000317.htm">ColdFusion Online-Hilfe</a> (<span class="webarchiv-memento"><a href="Webarchivierung#Begrifflichkeiten" title="Webarchivierung">Memento</a></span> vom 24. November 2006 im <i><a href="Internet_Archive" title="Internet Archive">Internet Archive</a></i>)</span>
</li>
</ol>
</div><!--htdig_noindex--><div><div class="zim-footer">
Dieser Artikel wurde von <a class="external text" title="Zuletzt bearbeitet am 2025-05-08" href="https://de.wikipedia.org/wiki/?title=SQL-Injection&amp;oldid=255831417">Wikipedia</a> herausgegeben. Der Text ist unter <a class="external text" href="https://creativecommons.org/licenses/by-sa/4.0/deed.de">Creative Commons Attribution-Share Alike 4.0</a> verfügbar, sofern nicht anders angegeben. Für die Mediendateien können zusätzliche Bedingungen gelten.
</div>
</div><!--/htdig_noindex--></div>
</div>
</main>
</div>
</div>
</div>
<script src="./_webp_/webpHandler.js"></script>

</body></html>